#include "core/manager.h"
#include <atomic>
#include <memory>
#include <unordered_map>
#include "log.h"
#include "core/context.h"
#include "utils/network.h"
#include "utils/wsa_init.h" //全局只需被包含一次
#include "utils/unique_ptr.h"
#include "utils/header_global.h"
#include "utils/diagnostic.h"
#include "modules/router.h"
#include "modules/broadcast.h"
#include "modules/agent.h"
#include "modules/synchronizer.h"
#include "modules/api.h"
#include "modules/regcenter.h"
#ifdef MOCK
#include "core/mock.h"
#endif

// #define LIFE_CYCLE_DEMONSTRATION // 生命周期演示，注释掉此宏以关闭
#define SELECT_TIMEOUT 1 // select超时时间

class GwManager::Impl {
private:
	shared_ptr<Context> context; // 全局上下文
	DEPRECATED("use thread pool")
	unique_ptr<thread> listener_thread;         // 监听器处理线程
	atomic<bool>       listener_running{false}; // 监听器运行状态

public:
	void multi_listener() { // 监听器处理程序
		while (listener_running) {
			auto sockets = context->getAllSockets();
			if (sockets.empty()) {
				this_thread::sleep_for(chrono::milliseconds(100));
				continue;
			}

			fd_set readfds;
			FD_ZERO(&readfds);
			int max_fd = 0;
			for (auto sock: sockets) {
				FD_SET(sock, &readfds);
				max_fd = max(max_fd, sock);
			}
			timeval timeout{SELECT_TIMEOUT, 0};
			int     ret = select(max_fd + 1, &readfds, nullptr, nullptr, &timeout);
			if (ret < 0) {
				log_error("[Manager] Selector error.");
				this_thread::sleep_for(chrono::milliseconds(1000));
				continue;
			}

			for (auto sock: sockets) {
				if (FD_ISSET(sock, &readfds)) {
					char               buffer[BUFFER_SIZE];
					struct sockaddr_in client_addr{};
					socklen_t          addr_len = sizeof(client_addr);
					ssize_t            len      = recvfrom(sock, buffer, BUFFER_SIZE, 0, (sockaddr *) &client_addr, &addr_len);
					if (len > 0) {
						if (auto *listener = context->getListenerByFD(sock)) {
							listener->handler(sock, buffer, len, inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
						} else {
							log_error("[Manager] Recvfrom unknown source.");
						}
					} else if (len < 0 && (errno == EBADF || errno == ENOTSOCK)) {
						context->removeByFd(sock);
					}
				}
			}
		}
	}

	bool init_network() noexcept {
		netutil::initNetWork();
		if (netutil::CURRENT_IP4.empty()) {
			DIAGNOSTIC_PUSH
			IGNORE_NOEXCEPT_SPEC
			throw std::runtime_error("current_ip4 error.");
			DIAGNOSTIC_POP
		}
		log_info("[Manager] Current IPv4: %s", netutil::CURRENT_IP4.c_str());
		return true;
	}

	bool init_config(const string &config_path, Configure &config) {
		if (config.Load(config_path) < 0) { // 覆盖配置
			log_info("[Manager] Using default config.");
		} else {
			log_info("[Manager] Using %s", config_path.c_str());
		}
		return true;
	}

	bool init_logger(Configure &cfg) {
		auto  logpath     = cfg.Logger.Path + "dump.log";
		FILE *logger_file = fopen(logpath.data(), "a");
		if (!logger_file) {
			throw std::runtime_error("Logger open failed: " + logpath);
		}
		log_add_fp(logger_file, cfg.Logger.levelVal());
		log_set_level(cfg.Logger.levelVal());
		log_set_quiet(cfg.Logger.Quiet);
		log_info("[Manager] Logger initialized.");
		// fclose(loggerFile);  //不能释放
		return true;
	}

#ifdef MOCK
	void load_mock_data(shared_ptr<Context> ctx) noexcept {
		biz::mock(ctx, netutil::CURRENT_IP4);
		log_info("[Manager] Loading mock data...");
	}
#endif

	void cfg_forecast(Configure &config) noexcept {
		printf("\n");
		// 检查日志输出
		log_set_level(LOG_DEBUG);
		log_debug("[DEBUG] [LOG] This is a debug message");
		log_info("[DEBUG] [LOG] This is an info message");
		log_warn("[DEBUG] [LOG] This is a warning message");
		log_error("[DEBUG] [LOG] This is an error message");
		log_fatal("[DEBUG] [LOG] This is a fatal message");
		log_info("[DEBUG] [LOG] Logger dump with format : %d", 9527);
		log_info("[DEBUG] [LOG] Logger dump with format : %s\n", "Hello");

		// 检查配置信息
		log_info("[DEBUG] [CFG] ProjectName         :  %s", config.Gateway.AppName.c_str());
		log_info("[DEBUG] [CFG] GatewayPort         :  %d", config.Gateway.GatewayPort);
		log_info("[DEBUG] [CFG] DynamicAgentPort    :  %d", config.Gateway.DynamicAgentPort);
		log_info("[DEBUG] [CFG] StaticAgentPort     :  %d", config.Gateway.StaticAgentPort);
		log_info("[DEBUG] [CFG] Multicast.Addr      :  %s", config.Multicast.Addr.c_str());
		log_info("[DEBUG] [CFG] Multicast.Port      :  %d", config.Multicast.Port);
		log_info("[DEBUG] [CFG] Multicast.Interval  :  %d", config.Multicast.Interval);
		log_info("[DEBUG] [CFG] Discovery.Addr      :  %s", config.Discovery.Addr.c_str());
		log_info("[DEBUG] [CFG] Discovery.Port      :  %d", config.Discovery.Port);
		log_info("[DEBUG] [CFG] Log.Path            :  %s", config.Logger.Path.c_str());
		if (config.Services.size() > 0) {
			log_info("[DEBUG] [CFG] Services[0]         :  %s\n", config.Services[0].Name.c_str());
		}
	}

	bool _module_load(shared_ptr<Context> ctx, unique_ptr<Module> module) {
		log_info("[Manager] Load module - %s", module->ModuleName().c_str());
		ctx->modules.push_back(move(module));
		return true;
	}

	bool init_modules(std::shared_ptr<Context> ctx) {
		// 1. 模块构造
		auto mod_router    = std::make_unique<mod::RouterModule>(ctx, MODULE_ROUTER);
		auto mod_breadcast = std::make_unique<mod::BreadcastModule>(ctx, MODULE_BREADCAST);
		auto mod_sync      = std::make_unique<mod::SyncModule>(ctx, MODULE_SYNC);
		auto mod_rc        = std::make_unique<mod::RegCenterModule>(ctx, MODULE_RegCenter);
		auto mod_agent     = std::make_unique<mod::AgentModule>(ctx, MODULE_AGENT);
		auto mod_api       = std::make_unique<mod::ApiModule>(ctx, MODULE_API);

		// 2. 模块加载
		// 注意：注册的顺序决定了模块加载的顺序,有依赖关系
		bool result = _module_load(ctx, move(mod_router)) &&    // 路由(网关引擎)
		              _module_load(ctx, move(mod_breadcast)) && // 广播
		              _module_load(ctx, move(mod_sync)) &&      // 同步
		              _module_load(ctx, move(mod_agent)) &&     // 代理
		              _module_load(ctx, move(mod_rc)) &&        // 注册中心
		              _module_load(ctx, move(mod_api));         // API
		if (!result) {
			throw std::runtime_error("modules load failed.");
		}
		printf("\n");

		// 3. 模块初始化
		for (auto &module: ctx->modules) {
			log_info("[Manager] Init module - %s", module->ModuleName().c_str());
			if (!module->Init()) {
				throw std::runtime_error("module init failed - " + module->ModuleName());
			}
		}
		printf("\n");
		return true;
	}

	void _module_unload(shared_ptr<Context> ctx) noexcept {
		// 反向卸载
		for (auto it = ctx->modules.rbegin(); it != ctx->modules.rend(); ++it) {
			log_info("[Manager] Unload module - %s", it->get()->ModuleName().c_str());
#ifndef LIFE_CYCLE_DEMONSTRATION
			it->get()->Stop();
#endif
		}
	}

public:
	Impl() {
		printf("\033[1;34m%*s\033[0m\n", 68, string(68, '=').c_str());
		printf("\033[1;34m%*sService Oriented Edge Gateway (v1.0.0)\033[0m\n", 15, string(15, ' ').c_str());
		printf("\033[1;34m%*s\033[0m\n", 68, string(68, '=').c_str());
	};

	bool Init(const std::string &config_path) {
		try {
			// 初始化网络
			if (!init_network()) return false;

			// 初始化配置
			auto &config = Configure::Instance();
			if (!init_config(config_path, config)) return false;

			// 初始化日志
			if (!init_logger(config)) return false;

			// 临时上下文(部分初始化)
			auto _ctx = std::make_shared<Context>(config);
#ifdef MOCK
			load_mock_data(_ctx); // !给上下文添加MOCK数据
#endif
#ifdef DEBUG
			cfg_forecast(config); //! 配置信息检查
#endif
			// 模块初始化
			if (!init_modules(_ctx)) return false;

			this->context = _ctx;
			return true;
		} catch (const std::exception &e) {
			printf("[Exception] GwManager init failed : %s", e.what());
			return false;
		}
	}

	void Run() {
		listener_running = true;
#ifdef LIFE_CYCLE_DEMONSTRATION
		for (auto &module: this->context->modules) {
			log_info("[Manager] Start module - %s", module->ModuleName().c_str());
		}

		printf("\n");
		log_info("Simulation running, please wait...\n");
		this_thread::sleep_for(chrono::milliseconds(3000));
#else
		listener_thread.reset(new thread([this]() { this->multi_listener(); }));
		for (auto &module: this->context->modules) {
			log_info("[Manager] Start module - %s", module->ModuleName().c_str());
			try {
				module->Start(); // 启动当前模块
			} catch (const std::exception &e) {
				log_fatal("[Manager] Failed to start module - %s, error: %s", module->ModuleName().c_str(), e.what());
				exit(1); // 直接退出程序
			} catch (...) {
				log_fatal("[Manager] Failed to start module - %s, unknown error", module->ModuleName().c_str());
				exit(1);
			}
		}
#endif
	}

	~Impl() {
#ifndef LIFE_CYCLE_DEMONSTRATION
		if (listener_thread->joinable()) {
			listener_thread->join();
		}
#endif
		// 注销所有模块
		_module_unload(this->context);
		listener_running = false;
		this->context.reset();
		log_info("[Manager] Resources released. Bye !!!");
	};
};

GwManager::GwManager() : pImpl(std::make_unique<Impl>()) {}
bool GwManager::Init(string config_path) { return this->pImpl->Init(config_path); }
void GwManager::Run() { this->pImpl->Run(); }
GwManager::~GwManager() = default;
